<!DOCTYPE html>
<html lang="zh-Hans">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=2">
<meta name="theme-color" content="#222">
<meta name="generator" content="Hexo 4.2.1">
  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32-next.png">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16-next.png">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">


<link rel="stylesheet" href="/lib/font-awesome/css/all.min.css">
  <link rel="stylesheet" href="/lib/pace/pace-theme-minimal.min.css">
  <script src="/lib/pace/pace.min.js"></script>

<script id="hexo-configurations">
    var NexT = window.NexT || {};
    var CONFIG = {"hostname":"sophimp.gitee.io","root":"/","scheme":"Pisces","version":"7.8.0","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12,"onmobile":false},"copycode":{"enable":false,"show_result":false,"style":null},"back2top":{"enable":true,"sidebar":false,"scrollpercent":true},"bookmark":{"enable":false,"color":"#222","save":"auto"},"fancybox":false,"mediumzoom":false,"lazyload":false,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"algolia":{"hits":{"per_page":10},"labels":{"input_placeholder":"Search for Posts","hits_empty":"We didn't find any results for the search: ${query}","hits_stats":"${hits} results found in ${time} ms"}},"localsearch":{"enable":false,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false},"motion":{"enable":true,"async":false,"transition":{"post_block":"fadeIn","post_header":"slideDownIn","post_body":"slideDownIn","coll_header":"slideLeftIn","sidebar":"slideUpIn"}}};
  </script>

  <meta name="description" content="Dagger2 是一个依赖注入框架, 以前也是收square开发的项目， 现在由google维护， 集成到了Jetpack套件中，依赖注入框架，还是能节省不少模板代码的。 Dagger2的使用相对复杂，没有流行起来，因此又出了一个hilt框架， 基于dagger, 省去使用dagger创建模板代码的部分，使用注解代替。">
<meta property="og:type" content="article">
<meta property="og:title" content="Dagger2-Hilt">
<meta property="og:url" content="http://sophimp.gitee.io/2021/01/11/android/jetpack/jetpack-dagger-hilt/index.html">
<meta property="og:site_name" content="Sophimp&#39;s Space">
<meta property="og:description" content="Dagger2 是一个依赖注入框架, 以前也是收square开发的项目， 现在由google维护， 集成到了Jetpack套件中，依赖注入框架，还是能节省不少模板代码的。 Dagger2的使用相对复杂，没有流行起来，因此又出了一个hilt框架， 基于dagger, 省去使用dagger创建模板代码的部分，使用注解代替。">
<meta property="article:published_time" content="2021-01-11T09:42:26.000Z">
<meta property="article:modified_time" content="2021-03-15T03:49:47.919Z">
<meta property="article:author" content="Sophimp">
<meta property="article:tag" content="Jetpack">
<meta property="article:tag" content="Dagger2">
<meta name="twitter:card" content="summary">

<link rel="canonical" href="http://sophimp.gitee.io/2021/01/11/android/jetpack/jetpack-dagger-hilt/">


<script id="page-configurations">
  // https://hexo.io/docs/variables.html
  CONFIG.page = {
    sidebar: "",
    isHome : false,
    isPost : true,
    lang   : 'zh-Hans'
  };
</script>

  <title>Dagger2-Hilt | Sophimp's Space</title>
  






  <noscript>
  <style>
  .use-motion .brand,
  .use-motion .menu-item,
  .sidebar-inner,
  .use-motion .post-block,
  .use-motion .pagination,
  .use-motion .comments,
  .use-motion .post-header,
  .use-motion .post-body,
  .use-motion .collection-header { opacity: initial; }

  .use-motion .site-title,
  .use-motion .site-subtitle {
    opacity: initial;
    top: initial;
  }

  .use-motion .logo-line-before i { left: initial; }
  .use-motion .logo-line-after i { right: initial; }
  </style>
</noscript>

</head>

<body itemscope itemtype="http://schema.org/WebPage">
  <div class="container use-motion">
    <div class="headband"></div>

	
	<script type="text/javascript" src="//cdn.bootcss.com/canvas-nest.js/1.0.0/canvas-nest.min.js"></script>
	

    <header class="header" itemscope itemtype="http://schema.org/WPHeader">
      <div class="header-inner"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="Toggle navigation bar">
      <span class="toggle-line toggle-line-first"></span>
      <span class="toggle-line toggle-line-middle"></span>
      <span class="toggle-line toggle-line-last"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <span class="logo-line-before"><i></i></span>
      <h1 class="site-title">Sophimp's Space</h1>
      <span class="logo-line-after"><i></i></span>
    </a>
      <p class="site-subtitle" itemprop="description">coding & thinking</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger">
    </div>
  </div>
</div>




<nav class="site-nav">
  <ul id="menu" class="main-menu menu">
        <li class="menu-item menu-item-home">

    <a href="/" rel="section"><i class="fa fa-home fa-fw"></i>Home</a>

  </li>
        <li class="menu-item menu-item-archives">

    <a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>Archives</a>

  </li>
  </ul>
</nav>




</div>
    </header>

    
  <div class="back-to-top">
    <i class="fa fa-arrow-up"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

  <a href="https://github.com/sophimp" class="github-corner" title="Follow me on GitHub" aria-label="Follow me on GitHub" rel="noopener" target="_blank"><svg width="80" height="80" viewBox="0 0 250 250" aria-hidden="true"><path d="M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"></path><path d="M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2" fill="currentColor" style="transform-origin: 130px 106px;" class="octo-arm"></path><path d="M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z" fill="currentColor" class="octo-body"></path></svg></a>


    <main class="main">
      <div class="main-inner">
        <div class="content-wrap">
          

          <div class="content post posts-expand">
            

    
  
  
  <article itemscope itemtype="http://schema.org/Article" class="post-block" lang="zh-Hans">
    <link itemprop="mainEntityOfPage" href="http://sophimp.gitee.io/2021/01/11/android/jetpack/jetpack-dagger-hilt/">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.png">
      <meta itemprop="name" content="Sophimp">
      <meta itemprop="description" content="A dream begin">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="Sophimp's Space">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          Dagger2-Hilt
        </h1>

        <div class="post-meta">
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-calendar"></i>
              </span>
              <span class="post-meta-item-text">Posted on</span>

              <time title="Created: 2021-01-11 17:42:26" itemprop="dateCreated datePublished" datetime="2021-01-11T17:42:26+08:00">2021-01-11</time>
            </span>
              <span class="post-meta-item">
                <span class="post-meta-item-icon">
                  <i class="far fa-calendar-check"></i>
                </span>
                <span class="post-meta-item-text">Edited on</span>
                <time title="Modified: 2021-03-15 11:49:47" itemprop="dateModified" datetime="2021-03-15T11:49:47+08:00">2021-03-15</time>
              </span>
            <span class="post-meta-item">
              <span class="post-meta-item-icon">
                <i class="far fa-folder"></i>
              </span>
              <span class="post-meta-item-text">In</span>
                <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
                  <a href="/categories/Android/" itemprop="url" rel="index"><span itemprop="name">Android</span></a>
                </span>
            </span>

          
            <span class="post-meta-item" title="Views" id="busuanzi_container_page_pv" style="display: none;">
              <span class="post-meta-item-icon">
                <i class="fa fa-eye"></i>
              </span>
              <span class="post-meta-item-text">Views: </span>
              <span id="busuanzi_value_page_pv"></span>
            </span>
            <div class="post-description">Dagger2 是一个依赖注入框架, 以前也是收square开发的项目， 现在由google维护， 集成到了Jetpack套件中，依赖注入框架，还是能节省不少模板代码的。 Dagger2的使用相对复杂，没有流行起来，因此又出了一个hilt框架， 基于dagger, 省去使用dagger创建模板代码的部分，使用注解代替。</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody">

      
        <h2 id="dagger2"><a href="#dagger2" class="headerlink" title="dagger2"></a>dagger2</h2><h3 id="是什么"><a href="#是什么" class="headerlink" title="是什么"></a>是什么</h3><p>Dagger2 是一个依赖注入框架, hilt 是为了简便dagger的使用， 省去一些模板代码。<br>现在使用一个框架默认最简的操作都是使用注解了么？</p>
<p><a href="https://developer.android.com/training/dependency-injection/manual?hl=zh-cn" target="_blank" rel="noopener">google Android 依赖注入文档</a><br><a href="https://dagger.dev/dev-guide/android" target="_blank" rel="noopener">官方user guide</a></p>
<h3 id="为什么"><a href="#为什么" class="headerlink" title="为什么"></a>为什么</h3><p>findViewById, 实例化一个对象这些操作，都属于一些模板代码。都可以优化成注解来简化使用, 减少出错的机率。</p>
<p>dagger 哲学</p>
<p>通常应用于Android代码的许多模式与其他Java代码的模式相反，即使有效的Java中的许多建议也被认为不适用于Android。<br>为了实现惯用代码和可移植代码的目标， Dagger 依靠ProGuard对已编译的字节码进行后处理，<br>这使得Dagger可以散发出在服务器和Android上看起来感觉自然的源代码，<br>同时使用不同的工具链来生成两种环境中都能高效执行的字节码。</p>
<p>Dagger 的明确目标是确保其生成的Java源代码始终与ProGuard优化兼容。</p>
<p>ProGuard又是什么,<br>    开源的java和kotlin优化器</p>
<h3 id="怎么做"><a href="#怎么做" class="headerlink" title="怎么做"></a>怎么做</h3><p>依赖注入的一条原则： 一个类不应该感知到被注入的任何细节。</p>
<p>构造函数注入<br>字段注入</p>
<p>生成中间代码, 在编译过程中， Dagger会检查代码并执行以下操作:</p>
<ul>
<li>构建并验证依赖关系图, 确保:<ul>
<li>每个对象的依赖关系都可以得到满足， 从而避免RuntimeException</li>
<li>不存在任何依赖循环， 从而避免出现无限循环。</li>
</ul>
</li>
<li>生成在运行时用于创建实际对象以及其依赖类项的类。</li>
</ul>
<p>最佳做法摘要:</p>
<ul>
<li>@Inject 进行构造函数注入， 向Dagger图中添加类型， 使用@Binds告知Dagger接口应采用哪种实现， 使用@Provides 告知 Dagger 如何提供您的项目所不具备的类。</li>
<li>只在在组件中声明一次模块</li>
<li>根据注解的使用生命周期, 为作用域注解命名。</li>
</ul>
<p>总结:<br>所谓的依赖就是一个类的实例化必须依赖另一个类先实例化，而另一个先实例化的类也可能会依赖于其他类先实例化， 这样就会形成一个依赖链，如果同时多个实例对象依赖实例化， 就形成依赖图。典型的例子就是 IO 的类家族依赖。<br>Dagger 所做的事就是将这个依赖创建对象的模板方法自动化。通过@Component 注解的类作为与上层应用沟通的接口人，同时管理依赖图, 维护依赖的生命周期。<br>那么简单的使用流程即时， @Inject 标注依赖注入的目标， @Module, @Provider 提供项目所不具备的类(系统或第三方框架), @Component 标注生成依赖图，上层应用通过调用此类的方法来获取具体对象。<br>@Component 支持域注解，实现单例模式。<br>多模块的注解使用</p>
<h2 id="Hilt"><a href="#Hilt" class="headerlink" title="Hilt"></a>Hilt</h2><h3 id="是什么-1"><a href="#是什么-1" class="headerlink" title="是什么"></a>是什么</h3><ol>
<li><p>目标</p>
<ul>
<li>使Dagger相关的基础架构更简单地应用到Android应用中。</li>
<li>创建一个标准的组件和作用域集, 简化设置，提高可读/可理解性， 以及应用间共享代码。</li>
<li>提供一个简单的方法供不同的构建类型(testing, debug, release)绑定。</li>
</ul>
</li>
<li><p>概览<br>hilt 是基于Dagger, 自动生成Dagger的设置代码。这避免手动编写Dagger的模板代码，只专注于创建变量，以及在哪里注入。<br>hilt 会生成 Dagger的Components依赖视图，并自动注入Android的类中(Activities 和 Fragments)</p>
</li>
<li><p>如何自动生成Components呢？<br>根据传入的类路径。通过hilt 注解，决定使用哪个Component, 在哪个Android Framework 类中去生成注入代码。 </p>
</li>
<li><p>如何生成注入代码扩展framework类呢？<br>对于gardle 构建的Android工程，在底层使用 bytecode transformation 来扩展</p>
</li>
<li><p>测试<br>Hilt 会像生产模式中一样生成 Dagger components, 有专门的测试工具来帮助添加或者替换成测试绑定。</p>
</li>
<li><p>优点<br>减少模板代码<br> hilt 鼓励使用一个全局的binding namespace, 可以简单地知道哪一个binding definition 被使用， 而不必去追溯从哪个activity或fragment注入<br>解耦构建依赖<br> Dagger components 有所有安装的modules引用依赖。这会导致依赖臃肿，降低编译速度。解决这个问题自然会涉及接口和非安全的强制转换。<br> hilt 在底层自动生成所有的接口，类型转换，module/interface 列表，保证了module/entry点发现，使运行时的非安全类型转换变得安全。<br>简化配置<br> 应用开发会有不同的编译构建配置，如生产环境和开发环境。不同的功能特性意味着不同的modules, 在常规的Dagger构建中， 不同的modules集意味着不同的componenttree, 这会导致很多重复的配置部分。<br> 因为hilt是自动生成这块代码，因此更加方便添加和移除那些依赖。<br>改良测试<br> Dagger是难于测试的，是因为上面提到的配置问题。同理对于测试的依赖配置，hilt也有专门的工具来自动生成, 从而减少了tests中的模板代码的编写(由hilt自动生成), 通过与在生产环境中实例化方式一样实例化测试环境中的代码， 使测试更加健壮。</p>
</li>
</ol>
<p>标准化components<br>    使components的层次结构标准化。</p>
<ol start="7">
<li>单一系统设计(monolithic system)</li>
</ol>
<p>单独的绑定空间 Single binding key space<br>    保持bindings只为特有的代码使用，推荐使用限定注解(qulifier annotation)通过限制可见性来保护, 或者使用SPI插件强制分隔代码。</p>
<p>简单的配置 Simplicity for Configuration<br>更少的代码生成 Less generated code<br>更快的lint检查， 延迟启动 fastlint and start up latency</p>
<ol start="8">
<li>Dagger SPI<br>hook Dagger’s annotation processor, 访问同一个graph model</li>
</ol>
<p>SPI plugin 原理<br>继承BindingGraphPlugin, @AutoService可以做到使用ServiceLoader加载,<br>当Dagger在classpath中检测到了 SPI plugin， 会调用 visitGraph(BindingGraph, DiagnosticReporter) 去遍历Dagger编译生成的合法的@Component,<br>如果所有的视图依赖检测通过, 都合法，Dagger 会继续使用visitGraph 去遍历所有的module, component, subcomponent 是否有错误。 在这种情况下，BindingGraph 可能包含有MissingBinding 节点。 </p>
<p>BindingGraph 被实现成 com.google.common.graph.Network, Network 中节点表示components, bindings, missing bindings这些节点。边代表父-子component 的依赖关系。 具体的实现看<a href="https://dagger.dev/api/latest/dagger/model/BindingGraph.html" target="_blank" rel="noopener">BindingGraph JavaDoc</a></p>
<ol start="9">
<li>Hilt gradle插件<br> 使用插件不必在@HiltAndroidApp注解后面带上Application要继承的类。</li>
</ol>
<h3 id="使用"><a href="#使用" class="headerlink" title="使用"></a>使用</h3><p>@HiltAndroidApp<br>    所有使用hilt的应用都有一个Application类加上@HiltAndroidApp 注解, 在需要依赖注入的变量前加上@Injected, 即可以调用super.onCreate()后使用<br>@AndroidEntryPoint<br>    Activity, Fragment, View, Service, BroadcastReceiver<br>    ViewModel 使用@HiltViewModel<br>    在 Fragment#onCreate 方法中调用 setRetainInstace(true) 会在configuration changes 时保持实例，而不是销毁再创建。</p>
<pre><code>Hilt Fragment 不能设计retained, 因为它持有Component引用， 而Component 持有 Activity引用, 这会造成内存泄漏。 另外， scope bindings 和 providers在Fragment retained的情况下也同样会造成内存泄漏。

BoradcastReceiver 不需要DaggerComponent, 共用SignletonComponent。</code></pre><p>@Inject<br>    用于构建函数, 或字段<br>@Module<br>@InstallIn<br>@Component<br>    注解一个interface, 会自动生成DaggerXXXComponent类， 提供create方法，可以调用 interface 中的方法。使用hilt gralde plugin, 这些都会自动生成。<br>    生命周期,  绑定对象的 create 与 destory方法, 标示着成员变量什么时候可以用。 </p>
<p><a href="https://dagger.dev/hilt/component-hierarchy.svg" target="_blank" rel="noopener">component 层次结构</a></p>
<table>
<thead>
<tr>
<th align="center">Component</th>
<th align="center">Scope</th>
<th align="center">Created at</th>
<th align="center">Destoryed at</th>
<th align="center">Default Bindings</th>
</tr>
</thead>
<tbody><tr>
<td align="center">SingletonComponent</td>
<td align="center">@Singleton</td>
<td align="center">Application#oncreate()</td>
<td align="center">Application#onDestroy()</td>
<td align="center">Application</td>
</tr>
<tr>
<td align="center">ActivityRetainedComponent</td>
<td align="center">@ActivityRetainedScoped</td>
<td align="center">Activity#onCreate()</td>
<td align="center">Activity#onDestroy()</td>
<td align="center">Application</td>
</tr>
<tr>
<td align="center">ViewModelComponent</td>
<td align="center">@ViewModelScoped</td>
<td align="center">ViewModel created</td>
<td align="center">ViewModel destroyed</td>
<td align="center">SavedStateHandle</td>
</tr>
<tr>
<td align="center">ActivityComponent</td>
<td align="center">@ActivityScoped</td>
<td align="center">Activity#onCreate()</td>
<td align="center">Activity#onDestroy()</td>
<td align="center">Application, Activity</td>
</tr>
<tr>
<td align="center">FragmentComponent</td>
<td align="center">@FragmentScoped</td>
<td align="center">Fragment#onAttach()</td>
<td align="center">Fragment#onDestroy()</td>
<td align="center">Application, Activity, Fragment</td>
</tr>
<tr>
<td align="center">ViewComponent</td>
<td align="center">@ViewScoped</td>
<td align="center">View#super()</td>
<td align="center">View destroyed</td>
<td align="center">Application, Activity, View</td>
</tr>
<tr>
<td align="center">ViewWithFragmentComponent</td>
<td align="center">@ViewScoped</td>
<td align="center">View#super()</td>
<td align="center">View destroyed</td>
<td align="center">Application, Activity, Fragment, View</td>
</tr>
<tr>
<td align="center">ServiceComponent</td>
<td align="center">@ServiceScoped</td>
<td align="center">Service#onCreate()</td>
<td align="center">Service#onDestroy()</td>
<td align="center">Application, Service</td>
</tr>
</tbody></table>
<p>注意，注解了@FragmentScoped 的Fragments 都有自己的FragmentComponent实例, @FragmentScoped 表示在其注入的Fragment中的相关依赖。</p>
<p>Scope Annotation 是有花销的, 因此仅在代码正确性所需要情况下才使用。 如果仅仅是因为想提升性能, 首先确认当前应用性能是不是一个问题，其次优先考虑使用@Reusable来替代component scope。</p>
<p>@Binds<br>@Provide</p>
<h3 id="改造模板LoginActivity"><a href="#改造模板LoginActivity" class="headerlink" title="改造模板LoginActivity"></a>改造模板LoginActivity</h3><p>使用hilt来改造模板Activity, </p>

    </div>

    
    
    

      <footer class="post-footer">
          <div class="post-tags">
              <a href="/tags/Jetpack/" rel="tag"># Jetpack</a>
              <a href="/tags/Dagger2/" rel="tag"># Dagger2</a>
          </div>

        


        
    <div class="post-nav">
      <div class="post-nav-item">
    <a href="/2021/01/08/android/jetpack/jetpack-lifecycle/" rel="prev" title="Jetpack - Lifecycle">
      <i class="fa fa-chevron-left"></i> Jetpack - Lifecycle
    </a></div>
      <div class="post-nav-item">
    <a href="/2021/01/23/android/android-dev-buffer/" rel="next" title="Android开发琐碎">
      Android开发琐碎 <i class="fa fa-chevron-right"></i>
    </a></div>
    </div>
      </footer>
    
  </article>
  
  
  



          </div>
          

<script>
  window.addEventListener('tabs:register', () => {
    let { activeClass } = CONFIG.comments;
    if (CONFIG.comments.storage) {
      activeClass = localStorage.getItem('comments_active') || activeClass;
    }
    if (activeClass) {
      let activeTab = document.querySelector(`a[href="#comment-${activeClass}"]`);
      if (activeTab) {
        activeTab.click();
      }
    }
  });
  if (CONFIG.comments.storage) {
    window.addEventListener('tabs:click', event => {
      if (!event.target.matches('.tabs-comment .tab-content .tab-pane')) return;
      let commentClass = event.target.classList[1];
      localStorage.setItem('comments_active', commentClass);
    });
  }
</script>

        </div>
          
  
  <div class="toggle sidebar-toggle">
    <span class="toggle-line toggle-line-first"></span>
    <span class="toggle-line toggle-line-middle"></span>
    <span class="toggle-line toggle-line-last"></span>
  </div>

  <aside class="sidebar">
    <div class="sidebar-inner">

      <ul class="sidebar-nav motion-element">
        <li class="sidebar-nav-toc">
          Table of Contents
        </li>
        <li class="sidebar-nav-overview">
          Overview
        </li>
      </ul>

      <!--noindex-->
      <div class="post-toc-wrap sidebar-panel">
          <div class="post-toc motion-element"><ol class="nav"><li class="nav-item nav-level-2"><a class="nav-link" href="#dagger2"><span class="nav-number">1.</span> <span class="nav-text">dagger2</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#是什么"><span class="nav-number">1.1.</span> <span class="nav-text">是什么</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#为什么"><span class="nav-number">1.2.</span> <span class="nav-text">为什么</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#怎么做"><span class="nav-number">1.3.</span> <span class="nav-text">怎么做</span></a></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#Hilt"><span class="nav-number">2.</span> <span class="nav-text">Hilt</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#是什么-1"><span class="nav-number">2.1.</span> <span class="nav-text">是什么</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#使用"><span class="nav-number">2.2.</span> <span class="nav-text">使用</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#改造模板LoginActivity"><span class="nav-number">2.3.</span> <span class="nav-text">改造模板LoginActivity</span></a></li></ol></li></ol></div>
      </div>
      <!--/noindex-->

      <div class="site-overview-wrap sidebar-panel">
        <div class="site-author motion-element" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="Sophimp"
      src="/images/avatar.png">
  <p class="site-author-name" itemprop="name">Sophimp</p>
  <div class="site-description" itemprop="description">A dream begin</div>
</div>
<div class="site-state-wrap motion-element">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
          <a href="/archives/">
        
          <span class="site-state-item-count">86</span>
          <span class="site-state-item-name">posts</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
            <a href="/categories/">
        <span class="site-state-item-count">19</span>
        <span class="site-state-item-name">categories</span></a>
      </div>
      <div class="site-state-item site-state-tags">
            <a href="/tags/">
        <span class="site-state-item-count">89</span>
        <span class="site-state-item-name">tags</span></a>
      </div>
  </nav>
</div>
  <div class="links-of-author motion-element">
      <span class="links-of-author-item">
        <a href="https://github.com/sophimp" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;sophimp" rel="noopener" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
      <span class="links-of-author-item">
        <a href="mailto:sophimp2020@126.com" title="E-Mail → mailto:sophimp2020@126.com" rel="noopener" target="_blank"><i class="fa fa-envelope fa-fw"></i>E-Mail</a>
      </span>
  </div>



      </div>

    </div>
  </aside>
  <div id="sidebar-dimmer"></div>


      </div>
    </main>

    <footer class="footer">
      <div class="footer-inner">
        

        

<div class="copyright">
  
  &copy; 
  <span itemprop="copyrightYear">2021</span>
  <span class="with-love">
    <i class="fa fa-heart"></i>
  </span>
  <span class="author" itemprop="copyrightHolder">Sophimp</span>
</div>

<!--
  <div class="powered-by">Powered by <a href="https://hexo.io/" class="theme-link" rel="noopener" target="_blank">Hexo</a> & <a href="https://pisces.theme-next.org/" class="theme-link" rel="noopener" target="_blank">NexT.Pisces</a>
  </div>
-->

        
<div class="busuanzi-count">
  <script async src="https://busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js"></script>
    <span class="post-meta-item" id="busuanzi_container_site_uv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-user"></i>
      </span>
      <span class="site-uv" title="Total Visitors">
        <span id="busuanzi_value_site_uv"></span>
      </span>
    </span>
    <span class="post-meta-divider">|</span>
    <span class="post-meta-item" id="busuanzi_container_site_pv" style="display: none;">
      <span class="post-meta-item-icon">
        <i class="fa fa-eye"></i>
      </span>
      <span class="site-pv" title="Total Views">
        <span id="busuanzi_value_site_pv"></span>
      </span>
    </span>
</div>








      </div>
    </footer>
  </div>

  
  <script src="/lib/anime.min.js"></script>
  <script src="/lib/velocity/velocity.min.js"></script>
  <script src="/lib/velocity/velocity.ui.min.js"></script>

<script src="/js/utils.js"></script>

<script src="/js/motion.js"></script>


<script src="/js/schemes/pisces.js"></script>


<script src="/js/next-boot.js"></script>




  















  

  

</body>
</html>
